package com.algorithm.qap;

import com.algorithm.basic.BasicMoead;
import com.problem.qap.QAPProblem;
import com.util.solution.impl.QAPSolution;

public class M2M extends BasicMoead{
	private QAPProblem problem;
	private int run_num;

	public M2M(QAPProblem problem, int type, int run_num){
		super(problem.obj_num, type);
		this.problem = problem;
		this.run_num = run_num;
		weights = new double[problem.sub_num*problem.obj_num];
		boolean ret = initialWeights(problem.sub_num, 0);
		this.problem.initialPopulation2(problem.sub_num, weights);
		if(!ret) System.exit(0);
		this.bind(this.problem);
	}

	public void initialIdealPoint(){
		for(int i=0;i<problem.sub_num;i++){
			int [] values = problem.solutionArray[i].object_val;
			this.udpateIdealPoint(values);
		}
	}
	public void execute(int iteration){
		long startMili=System.currentTimeMillis();
		for(int i = 0;i<iteration;i++){
			System.out.println("iteration of : "+(i+1));
			this.executeMoead();
		}
		long endMili=System.currentTimeMillis();
		System.out.println((endMili-startMili)/1000+" s ");
		String fileName;
		fileName = "F:/科研论文/m2m/"+problem.fac_num+"-"+problem.obj_num+"/"+this.problem.corr+"/"+problem.fac_num+"_"+problem.obj_num+"_tch_"+run_num+".txt";
		problem.saveResults(fileName);
	}
	
	public void executeMoead(){
		for(int i=0;i<problem.sub_num;i++){
			QAPSolution curSolution = problem.solutionArray[i];
			if(curSolution.locations!=null && curSolution.isSearched()==false){
				problem.solutionArray[i].setSearched(true);
				try {
					QAPSolution s = curSolution.clone();
					this.generateNeighborhood(s);
				} catch (CloneNotSupportedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	/**
	 * generate the neighborhood of s
	 * @param s
	 */
	public void generateNeighborhood(QAPSolution s){
		int [] seq = s.getLocations().clone();
		for(int i=0;i<problem.fac_num;i++){
			for(int j=i+1;j<problem.fac_num;j++){
				int [] changedVal = new int[problem.obj_num];
				for(int k=0;k<problem.obj_num;k++) changedVal[k] = 0;
				for(int k=0;k<problem.obj_num;k++){
					for(int t=0;t<this.problem.fac_num;t++){
						changedVal[k] += 2*(this.problem.distMatrix[i*this.problem.fac_num+t]*this.problem.flowMatrix[k*this.problem.fac_num*this.problem.fac_num+seq[i]*this.problem.fac_num+seq[t]]);
						changedVal[k] += 2*(this.problem.distMatrix[j*this.problem.fac_num+t]*this.problem.flowMatrix[k*this.problem.fac_num*this.problem.fac_num+seq[j]*this.problem.fac_num+seq[t]]);
					}
				}
				QAPSolution temp = new QAPSolution(this.problem.fac_num, this.problem.obj_num, -1);
				temp.setLocations(seq.clone());
				temp.locations[i] = seq[j];
				temp.locations[j] = seq[i];
				for(int k=0;k<this.problem.obj_num;k++){
					for(int t=0;t<this.problem.fac_num;t++){
						changedVal[k] -= 2*(this.problem.distMatrix[i*this.problem.fac_num+t]*this.problem.flowMatrix[k*this.problem.fac_num*this.problem.fac_num+temp.locations[i]*this.problem.fac_num+temp.locations[t]]);
						changedVal[k] -= 2*(this.problem.distMatrix[j*this.problem.fac_num+t]*this.problem.flowMatrix[k*this.problem.fac_num*this.problem.fac_num+temp.locations[j]*this.problem.fac_num+temp.locations[t]]);
					}
				}
				int t_count = 0;
				for(int k=0;k<this.problem.obj_num;k++){
					if(changedVal[k]<=0){
						t_count++;
					}
				}
				if(t_count==this.problem.obj_num){
					continue;
				}
				for(int k=0;k<this.problem.obj_num;k++) temp.object_val[k] = s.object_val[k] - changedVal[k];
				temp.index = s.index;
				this.udpateSubSolutions(temp);
			}
		}
	}
	
	public boolean udpateSubSolutions(QAPSolution s){
		int index = this.problem.getIndex(s, this.problem.sub_num, weights);
		this.udpateIdealPoint(s.object_val);
		boolean ret = false;
		QAPSolution curSolution = problem.solutionArray[index];
		if(curSolution.locations==null) {
			curSolution.object_val = s.object_val.clone();
			curSolution.locations = s.locations.clone();
			curSolution.setSearched(false);
			ret = true;
		}else {
			double fitness = 0;
			curSolution.fitness = getTchValue(index, curSolution.object_val);
			fitness = getTchValue(index, s.object_val);
			if(curSolution.fitness>fitness){
				curSolution.object_val = s.object_val.clone();
				curSolution.locations = s.locations.clone();
				curSolution.setSearched(false);
				ret = true;
			}
		}
		return ret;
	}
	public static void main(String[]args){
		for(int i=0;i<1;i++){
			QAPProblem qap = new QAPProblem(); 
			M2M moead = new M2M(qap, -1, i);
			moead.execute(1000);
		}
	}
}
